//
// Created by czm on 2023/12/12.
//

#include "RfidScanner.h"

/* BLE */
#include "esp_nimble_hci.h"
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"
#include "host/ble_hs.h"
#include "host/util/util.h"
#include "console/console.h"
#include "services/gap/ble_svc_gap.h"

#include "../utils/CardUtils.h"

#define TAG "RfidScanner"

RfidScanner::RfidScanner():m_ant_index(0),m_last_send_time(0) {
    const uart_config_t uart_config = {
            .baud_rate = 57600,
            .data_bits = UART_DATA_8_BITS,
            .parity = UART_PARITY_DISABLE,
            .stop_bits = UART_STOP_BITS_1,
            .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
            .rx_flow_ctrl_thresh = 0,
            .source_clk = UART_SCLK_APB,
    };
    m_pPort = new SerialPort(RFID_PORT_NUM, uart_config, RFID_PORT_TX, RFID_PORT_RX);
    xTaskCreate(code_receive_task, "port1", 1024 * 5, this, 1, nullptr);
}

RfidScanner::~RfidScanner() {
    delete m_pPort;
}

void RfidScanner::code_receive_task(void *arg) {
    //点亮电源灯
    gpio_set_level(LED_POWER,1);
    int64_t running_time = 0;
    bool led_on = false;
    auto *pSelf = (RfidScanner *) arg;
//    vTaskDelay(100 / portTICK_PERIOD_MS);
//    pSelf->setPowerLevel(30); //设置最大发射功率
//    vTaskDelay(100 / portTICK_PERIOD_MS);
//    pSelf->setBeepOn(false); //关闭蜂鸣声
//    vTaskDelay(100 / portTICK_PERIOD_MS);
    while (true) {
        int64_t now = esp_timer_get_time();
        if(g_notify_flag){
            if((now- pSelf->m_last_send_time)>RFID_SEND_CMD_DELAY){
                pSelf->sendStart();
                pSelf->m_last_send_time = now;
                gpio_set_level(LED_RUNNING,1);
                running_time = now;
                led_on = true;
            }else{
                pSelf->procReceive();
                if(led_on && ((now-running_time)>100000)){
                    gpio_set_level(LED_RUNNING,0);
                    led_on = false;
                }
            }
        }else{
            g_pCardUtils->reset();
            if(led_on){
                gpio_set_level(LED_RUNNING,0);
                led_on = false;
            }
       }
        vTaskDelay(100 / portTICK_PERIOD_MS);
//        ESP_LOGI(TAG,"RUNNING g_notify_flag=%d now=%lld...",g_notify_flag, now);
    }
}

uint16_t RfidScanner::calcCrc(uint8_t *buf, int len) {
    uint16_t result = 0xFFFF;
    for (int i = 0; i < len; i++) {
        result ^= (buf[i] & 0xff);
        for (int j = 0; j < 8; j++) {
            if ((result & 0x01) != 0) {
                result = (result >> 1) ^ 0x8408;
            } else {
                result = result >> 1;
            }
        }
    }
    return result & 0xFFFF;
}

void RfidScanner::fillCrc(uint8_t *buf, int len) {
    uint16_t crc = calcCrc(buf,len-2);
    buf[len-2] = crc & 0xFF;
    buf[len-1] = (crc >> 8) & 0xFF;
}

void RfidScanner::sendStart() {
    uint8_t ant = 0x80 + m_ant_index;
    uint8_t buf[10] = {0x09, 0x00, 0x01, 0x04, 0x00, 0x00, ant, 0x0A, 0x00, 0x00}; //寻卡
    fillCrc(buf,sizeof(buf));
    m_pPort->write(buf,sizeof(buf));
//    ESP_LOGI(TAG,"Send Inventory Cmd ant=%d",m_ant_index);
    m_ant_index = (m_ant_index + 1) % RFID_ANT_COUNT;
}

void RfidScanner::setBeepOn(bool on){
    uint8_t flag = on ? 0x01 : 0x00;
    uint8_t buf[] = {0x05, 0x00, 0x40, flag, 0x00, 0x00}; //设置工作模式,掉电保存
    fillCrc(buf,sizeof(buf));
    m_pPort->write(buf,sizeof(buf));
}

void RfidScanner::setPowerLevel(uint8_t level){
    uint8_t buf[] = {0x05, 0x00, 0x2f, level, 0x00, 0x00}; //设置工作模式,掉电保存
    fillCrc(buf,sizeof(buf));
    m_pPort->write(buf,sizeof(buf));
}

void RfidScanner::procReceive() {
    int len = m_pPort->read();
    if(len <= 0){  //没有读到数据
        return;
    }
    do {
        int bufLen = m_pPort->getBufLen();
        if (bufLen < 5) { //至少需要5个字节
            ESP_LOGI(TAG,"Not enough data len=%d",bufLen);
            break; //等待下次进入
        }
        uint8_t *buf = m_pPort->getBuf();
        uint8_t dataLen = buf[0];
        if (dataLen < 5){
            m_pPort->decRecBuf(1);
            continue;
        }
        if(buf[1] != 0x00){ //地址不对
            m_pPort->decRecBuf(1);
            continue;
        }
        if(bufLen < dataLen + 1) { //数据不够
            ESP_LOGI(TAG,"Not enough dataLen=%d len=%d",dataLen, bufLen);
            ESP_LOG_BUFFER_HEX(TAG,buf,bufLen);
            break;
        }
        uint16_t crc16 = calcCrc(buf, dataLen - 1);
        if (buf[dataLen - 1] == (crc16 & 0xFF) && buf[dataLen] == ((crc16 >> 8) & 0xFF)) { //CRC验证通过
            parseResponse(buf, dataLen + 1);
            m_pPort->decRecBuf(1 + dataLen);
        } else {
            ESP_LOGI(TAG,"CRC ERROR crc16=%04X",crc16);
            ESP_LOG_BUFFER_HEX(TAG,buf,bufLen);
            m_pPort->decRecBuf(1);
        }
    } while (true);
}

void RfidScanner::parseResponse(uint8_t* buf, int dataLen){
    uint8_t reCmd = buf[2];
    uint8_t status = buf[3];
    if (reCmd == 0x01) { //询查标签
        if (status == 0x26) { //询查结束包
            int readRate = (buf[5] << 8) + buf[6];
            int foundNum = (buf[7] << 24) + (buf[8] << 16) + (buf[9] << 8) + buf[10];
            ESP_LOGI(TAG,"Finished readRate=%d foundNum=%d",readRate, foundNum);
        } else if (status == 0x01 || status == 0x02 || status == 0x03 || status == 0x04) {
//            int ant = buf[4];
//            int num = buf[5];
            for (int i = 6; i < dataLen - 2; ) {
                int epcLen = buf[i];
                char szCard[epcLen*2+2];
                memset(szCard,0,sizeof(szCard));
                int ii = i + 1;
                char* p = szCard;
                for (; ii < i + 1 + epcLen; ii++) {
                    sprintf(p,"%02X",buf[ii]);
                    p+=2;
                }
                *p = '\n';
                ESP_LOGI(TAG,"found card1=%s",szCard);

                if(g_pCardUtils){
                    g_pCardUtils->addCard(szCard);
                }
//                int rssi = buf[ii];
//                emitter.onNext(new CardInfo(sb.toString(), ant, rssi));

//                struct os_mbuf *om = ble_hs_mbuf_from_flat(szCard, strlen(szCard));
//                int rc = ble_gattc_notify_custom(g_conn_handle, g_card_notify_handle, om);
//                ESP_LOGI(TAG,"notify rc=%d card=%s",rc,szCard);
                i += epcLen + 2;
            }
            if (status != 0x03) {
//                emitter.onNext(new FinishResponse(reCmd, true));
            }
        } else {
//            emitter.onNext(new FinishResponse(reCmd, false));
        }
//    } else if (reCmd == (byte) 0xee) {
//        if (status == 0x00) { //读到符合条件的标签
//            int ant = buf[4];
//            int num = buf[5];
//            StringBuilder sb = new StringBuilder();
//            if(buf[6] == 'R' || buf[6] == 'r'){
//                for (int i = 0; i < num; i++) {
//                    if(buf[6+i] != 0x00) {
//                        sb.append((char) buf[6 + i]);
//                    }
//                }
//            }else {
//                for (int i = 0; i < num; i++) {
//                    String hex = Integer.toHexString(buf[6 + i] & 0xFF);
//                    if (hex.length() == 1) {
//                        sb.append("0");
//                    }
//                    sb.append(hex.toUpperCase());
//                }
//            }
//            int rssi = buf[6 + num];
//            emitter.onNext(new CardInfo(sb.toString(), ant, rssi));
//        } else if (status == 0x28) {//心跳包时间间隔内没有读到符合条件的标签，上传心跳包数据
//            LogUtils.d("自动询查心跳包");
//        }
//    } else if (reCmd == 0x21) { //读写器信息
//        if (buf[3] == 0x00) { //状态
//            RfidDevInfo devInfo = new RfidDevInfo(buf, 4);
//            PowerLevel powerLevel = new PowerLevel();
//            powerLevel.powerLevel = devInfo.power;
//            emitter.onNext(powerLevel);
//        } else {
//            emitter.onNext(new FinishResponse(reCmd, false));
//        }
//    }else if(reCmd == 0x77){
//        if(buf[3] == 0x00){
//            RfidWorkMode rfidWorkMode = new RfidWorkMode(buf,4);
//            emitter.onNext(rfidWorkMode);
//        } else {
//            emitter.onNext(new FinishResponse(reCmd, false));
//        }
//    } else {
//        emitter.onNext(new FinishResponse(reCmd, buf[3] == 0x00));
    }

}
